package com.mine.webviewtest;

import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.support.v4.content.FileProvider;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.webkit.JavascriptInterface;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.util.HashMap;
import java.util.Set;

public class MainActivity extends AppCompatActivity {

    WebView mWebView;
    Button mButton;
    private String mCameraFilePath;
    public static final int REQUEST_CODE_FILE_CHOOSER = 3;
    private ValueCallback<Uri> mUploadCallBack;
    private ValueCallback<Uri[]> mUploadCallBackAboveL;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mWebView = findViewById(R.id.wv);
        mButton = findViewById(R.id.btn);

        // 获取WebSetting对象
        WebSettings webSettings = mWebView.getSettings();
        // 设置支持javascript
        webSettings.setJavaScriptEnabled(true);
        // 设置允许JS弹窗
        webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//
            webSettings.setMixedContentMode(android.webkit.WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }

        mWebView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
                return super.onJsAlert(view, url, message, result);
            }

            @Override
            public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
                // 根据协议的参数进行拦截,下面拦截"callandroid://test"
                // 一般根据scheme & authority判断
                Uri uri = Uri.parse(message);//message是由JS的prompt()传来的
                // 如果 scheme  = callAndroid，即代表都符合约定的协议
                if (uri.getScheme() != null && uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test，即代表都符合约定的协议
                    if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法

                        // 可以获取参数
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }
                        //将返回值返回给JS
//                        result.confirm();//true
                        result.cancel();//false
                    }
                    return true;
                }
                return super.onJsConfirm(view, url, message, result);
            }

            @Override
            public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
                // 根据协议的参数进行拦截,下面拦截"callandroid://test"
                // 一般根据scheme & authority判断
                Uri uri = Uri.parse(message);//message是由JS的prompt()传来的
                // 如果 scheme  = callAndroid，即代表都符合约定的协议
                if (uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test，即代表都符合约定的协议
                    if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法

                        // 可以获取参数
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }
                        //将返回值返回给JS
                        result.confirm("拦截Prompt成功啦,传进来的参数是：" + params.toString());
                    }
                    return true;
                }
                return super.onJsPrompt(view, url, message, defaultValue, result);
            }

            // For Android < 3.0
            public void openFileChooser(ValueCallback<Uri> valueCallback) {
                mUploadCallBack = valueCallback;
                showFileChooser();
            }

            // For Android  >= 3.0
            public void openFileChooser(ValueCallback valueCallback, String acceptType) {
                mUploadCallBack = valueCallback;
                showFileChooser();
            }

            //For Android  >= 4.1
            public void openFileChooser(ValueCallback<Uri> valueCallback, String acceptType, String capture) {
                mUploadCallBack = valueCallback;
                showFileChooser();
            }

            // For Android >= 5.0
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
                mUploadCallBackAboveL = filePathCallback;
                showFileChooser();
                return true;
            }
        });
        mWebView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // 根据协议的参数进行拦截,下面拦截"callandroid://test"
                // 一般根据scheme & authority判断
                Uri uri = Uri.parse(url);
                // 如果 scheme  = callAndroid，即代表都符合约定的协议
                if (uri.getScheme() != null && uri.getScheme().equals("callandroid")) {

                    // 如果 authority  = test，即代表都符合约定的协议
                    if (uri.getAuthority().equals("test")) {// 拦截url,下面开始执行Android的方法

                        Toast.makeText(MainActivity.this, "js通过拦截调用了Android的方法", Toast.LENGTH_SHORT).show();
                        // 可以获取参数
                        HashMap<String, String> params = new HashMap<>();
                        Set<String> paramNames = uri.getQueryParameterNames();
                        for (String name : paramNames) {
                            params.put(name, uri.getQueryParameter(name));
                        }
                        Log.e("web-test", params.toString());

                    }

                    return true;
                }
                return super.shouldOverrideUrlLoading(view, url);

            }

        });

        // 通过addJavascriptInterface()将Java对象映射到JS对象
        mWebView.addJavascriptInterface(new CallByJS(), "androidObj");


        //加载assets里的test.html
        mWebView.loadUrl("file:///android_asset/test.html");
//        mWebView.loadUrl("http://gif.55.la/");
        //加载网页
        //mWebView.loadUrl("https://www.baidu.com/");
        mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //调用js要在webview加载完才可以调用
                mWebView.post(new Runnable() {
                    @Override
                    public void run() {
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
                            //方法名fucn1要写对，传入的参数要用单引号或双引号引用，双引号注意要用转义字符
                            mWebView.loadUrl("javascript:func1('a1a')");
                        } else {//版本19以上使用下面方法

                            mWebView.evaluateJavascript("javascript:func1('a1a')", new ValueCallback<String>() {
                                @Override
                                public void onReceiveValue(String value) {//value为 js 返回的值
                                    Toast.makeText(MainActivity.this, value, Toast.LENGTH_SHORT).show();
                                }
                            });
                        }
                    }
                });
            }
        });
    }


    /**
     * 打开选择文件/相机
     */
    private void showFileChooser() {

//        Intent intent1 = new Intent(Intent.ACTION_PICK, null);
//        intent1.setDataAndType(
//                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/*");
        Intent intent1 = new Intent(Intent.ACTION_GET_CONTENT);
        intent1.addCategory(Intent.CATEGORY_OPENABLE);
        intent1.setType("*/*");

        Intent intent2 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        mCameraFilePath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator +
                System.currentTimeMillis() + ".jpg";
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            // android7.0注意uri的获取方式改变
            Uri photoOutputUri = FileProvider.getUriForFile(
                    MainActivity.this,
                    BuildConfig.APPLICATION_ID + ".fileProvider",
                    new File(mCameraFilePath));
            intent2.putExtra(MediaStore.EXTRA_OUTPUT, photoOutputUri);
        } else {
            intent2.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(mCameraFilePath)));
        }

        Intent chooser = new Intent(Intent.ACTION_CHOOSER);
        chooser.putExtra(Intent.EXTRA_TITLE, "File Chooser");
        chooser.putExtra(Intent.EXTRA_INTENT, intent1);
        chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[]{intent2});
        startActivityForResult(chooser, REQUEST_CODE_FILE_CHOOSER);
    }

    public class CallByJS {
        // 被JS调用的方法必须加@JavascriptInterface注解
        @JavascriptInterface
        public void callByJS(String str) {
            Log.e("web_test", str);
        }
    }

    /*
     * Intent { dat=content://com.android.providers.media.documents/document/image:356700 flg=0x1 }--Intent.ACTION_GET_CONTENT
     * Intent { dat=content://media/external/file/356727 typ=application/pdf flg=0x3 }--Intent.ACTION_GET_CONTENT选择pdf返回得到的,这个uri直接传给h5会出现问题，要先获取path在转uri
     * Intent { dat=content://media/external/images/media/353547 flg=0x1 (has extras) }--Intent.ACTION_PICK
     *
     * file:///storage/emulated/0/1548674734485.jpg
     * /data/user/0/com.mine.webviewtest/cache/photos/1548674812409.jpg
     * content://com.mine.webviewtest.fileProvider/root_path/data/data/com.mine.webviewtest/cache/photos/1548674812409.jpg
     *
     * /storage/emulated/0/Android/data/com.mine.webviewtest/cache/photos/1548675064105.jpg
     * content://com.mine.webviewtest.fileProvider/beta_external_files_path/com.mine.webviewtest/cache/photos/1548675064105.jpg
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_CODE_FILE_CHOOSER) {
            Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
            if (result == null && !TextUtils.isEmpty(mCameraFilePath)) {
                // 看是否从相机返回
                File cameraFile = new File(mCameraFilePath);
                if (cameraFile.exists()) {
                    result = Uri.fromFile(cameraFile);
                    sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, result));
                }
            }
            if (result != null) {
                //非图片类型的uri返回给web可能用不了，要执行下面代码
                String path = FileUtils.getPath(this, result);
                if (!TextUtils.isEmpty(path)) {
                    File f = new File(path);
                    if (f.exists() && f.isFile()) {
                        Uri newUri = Uri.fromFile(f);
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            if (mUploadCallBackAboveL != null) {
                                if (newUri != null) {
                                    mUploadCallBackAboveL.onReceiveValue(new Uri[]{newUri});
                                    mUploadCallBackAboveL = null;
                                    return;
                                }
                            }
                        } else if (mUploadCallBack != null) {
                            if (newUri != null) {
                                mUploadCallBack.onReceiveValue(newUri);
                                mUploadCallBack = null;
                                return;
                            }
                        }
                    }
                }
            }
            clearUploadMessage();
            return;
        }
    }

    /**
     * webview没有选择文件也要传null，防止下次无法执行
     */
    private void clearUploadMessage() {
        if (mUploadCallBackAboveL != null) {
            mUploadCallBackAboveL.onReceiveValue(null);
            mUploadCallBackAboveL = null;
        }
        if (mUploadCallBack != null) {
            mUploadCallBack.onReceiveValue(null);
            mUploadCallBack = null;
        }
    }

}
